home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Networking / OT PAPServerSample / StringUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  15.5 KB  |  787 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        StringUtils.c
  3.  
  4.     Contains:    
  5.  
  6.     Written by:     
  7.  
  8.     Copyright:    Copyright © 1988-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 7/22/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 
  21.  
  22. */
  23.  
  24. #ifndef __MEMORY__
  25. #include <Memory.h>
  26. #endif
  27.  
  28. #ifndef __STRINGUTILS__
  29. #include "StringUtils.h"
  30. #endif
  31.  
  32. #ifndef __COMPENV__
  33. #include "CompEnv.h"
  34. #endif
  35.  
  36.  
  37.  
  38. /* These functions should be linked into whatever segment holds main().  This will
  39. ** guarantee that the functions will always be in memory when called.  It is important
  40. ** that they are in memory, because if a pointer is passed in that points into an
  41. ** unlocked handle, the mere fact that the code needs to get loaded may cause the
  42. ** handle that is pointed into to move.  If you stick to these string functions,
  43. ** you will not have to worry about the handle moving when the string function is
  44. ** called.  If you have your own string functions, and you wish the same safety
  45. ** factor, link the string handling code into the same segment as main(), as you
  46. ** do with these string functions. */
  47.  
  48. static short    gBase;
  49. static Boolean    gHandleChars;
  50.  
  51.  
  52.  
  53. /*****************************************************************************/
  54. /*****************************************************************************/
  55.  
  56. #ifdef applec
  57. #pragma segment ATGStringUtils
  58. #endif
  59.  
  60. /*****************************************************************************/
  61. /*****************************************************************************/
  62.  
  63.  
  64.  
  65. /* Return the length of the c-string.  (Same as strlen, but this function isn't
  66. ** part of the string library.  The entire library may be more than you wish to
  67. ** link into the code segment that holds main, so this (and other) standard
  68. ** library function has been duplicated here. */
  69.  
  70. short    clen(char *cptr)
  71. {
  72.     short    i;
  73.  
  74.     for (i = 0; cptr[i]; ++i) {};
  75.     return(i);
  76. }
  77.  
  78.  
  79.  
  80. /*****************************************************************************/
  81.  
  82.  
  83.  
  84. /* Catenate two c-strings. */
  85.  
  86. char    *ccat(char *s1, char *s2)
  87. {
  88.     ccpy(s1 + clen(s1), s2);
  89.     return(s1);
  90. }
  91.  
  92.  
  93.  
  94. /*****************************************************************************/
  95.  
  96.  
  97.  
  98. /* Copy a c-string. */
  99.  
  100. char    *ccpy(char *s1, char *s2)
  101. {
  102.     char    *c1, *c2;
  103.  
  104.     c1 = s1;
  105.     c2 = s2;
  106.     while ((*c1++ = *c2++) != 0) {};
  107.     return(s1);
  108. }
  109.  
  110.  
  111.  
  112. /*****************************************************************************/
  113.  
  114.  
  115.  
  116. /* Compare two pascal-strings. */
  117.  
  118. short    pcmp(StringPtr s1, StringPtr s2)
  119. {
  120.     short    i, len, j;
  121.  
  122.     if ((len = s1[0]) > s2[0]) len = s2[0];
  123.  
  124.     for (i = 1; i <= len; ++i) {
  125.         j = ((unsigned short)s1[i] - (unsigned short)s2[i]);
  126.         if (j) return(j);
  127.     }
  128.  
  129.     return(s1[0] - s2[0]);
  130. }
  131.  
  132.  
  133.  
  134. /*****************************************************************************/
  135.  
  136.  
  137.  
  138. /* Catenate two pascal-strings. */
  139.  
  140. void    pcat(StringPtr d, StringPtr s)
  141. {
  142.     short    i, j;
  143.  
  144.     if (((j = s[0]) + d[0]) > 255)
  145.         j = 255 - d[0];
  146.             /* Limit dest string to 255. */
  147.  
  148.     for (i = 0; i < j;) d[++d[0]] = s[++i];
  149. }
  150.  
  151.  
  152.  
  153. /*****************************************************************************/
  154.  
  155.  
  156.  
  157. /* Copy a pascal-string. */
  158.  
  159. void    pcpy(StringPtr d, StringPtr s)
  160. {
  161.     short    i;
  162.  
  163.     i = *s;
  164.     do {
  165.         d[i] = s[i];
  166.     } while (i--);
  167. }
  168.  
  169.  
  170.  
  171. /*****************************************************************************/
  172.  
  173.  
  174.  
  175. /* Convert a c-string to a pascal-string. */
  176.  
  177. void    c2p(char *cptr)
  178. {
  179.     short    len;
  180.  
  181.     BlockMove(cptr, cptr + 1, len = clen(cptr));
  182.     *cptr = len;
  183. }
  184.  
  185.  
  186.  
  187. /*****************************************************************************/
  188.  
  189.  
  190.  
  191. /* Convert a pascal-string to a c-string. */
  192.  
  193. void    p2c(StringPtr cptr)
  194. {
  195.     unsigned char    len;
  196.  
  197.     BlockMove(cptr + 1, cptr, len = *cptr);
  198.     cptr[len] = 0;
  199. }
  200.  
  201.  
  202.  
  203. /*****************************************************************************/
  204. /*****************************************************************************/
  205. /*****************************************************************************/
  206.  
  207.  
  208.  
  209. /* Catenate a single character multiple times onto the designated string. */
  210.  
  211. void    ccatchr(char *cptr, char c, short count)
  212. {
  213.     ccpychr(cptr + clen(cptr), c, count);
  214. }
  215.  
  216.  
  217.  
  218. /*****************************************************************************/
  219.  
  220.  
  221.  
  222. /* Convert the value into text for the base-10 number and catenate it to
  223. ** the designated string.  The value is assumed to be signed.  If you wish
  224. ** to have an unsigned decimal value, call ccatnum with a base of 10. */
  225.  
  226. void    ccatpaddec(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  227. {
  228.     ccatpadnum(cptr + clen(cptr), padChr, minApnd, maxApnd, v, -10);
  229.         /* Catenate value base 10, signed. */
  230. }
  231.  
  232. void    ccatdec(char *cptr, long v)
  233. {
  234.     ccatnum(cptr, v, -10);
  235. }
  236.  
  237.  
  238.  
  239. /*****************************************************************************/
  240.  
  241.  
  242.  
  243. /* Convert the value into text for base-16, format it, and catenate it to the
  244. ** designated string.  ccatnum could be used, since it handles multiple bases,
  245. ** but ccathex allows for additional common formatting and padding of the
  246. ** hex value. */
  247.  
  248. void    ccatpadhex(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  249. {
  250.     char    str[33], *sptr;
  251.     short    len;
  252.  
  253.     cptr += clen(cptr);            /* We're appending, so point to the end of the string. */
  254.     ccpynum(str, v, 16);        /* Generate minimum-digit hex value. */
  255.  
  256.     if ((len = clen(sptr = str)) > maxApnd)
  257.         sptr = str + len - maxApnd;
  258.  
  259.     if ((len = clen(sptr)) < minApnd)
  260.         if (padChr)
  261.             ccatchr(cptr, padChr, (minApnd - len));
  262.                 /* if we have a pad character, and if necessary, pad the string. */
  263.  
  264.     ccat(cptr, sptr);            /* Add the hex digits to the string. */
  265. }
  266.  
  267. void    ccathex(char *cptr, long v)
  268. {
  269.     ccatpadhex(cptr, 0, 0, 8, v);
  270. }
  271.  
  272.  
  273.  
  274. /*****************************************************************************/
  275.  
  276.  
  277.  
  278. /* Convert the value into text for the designated base.  Catenate the text to
  279. ** the designated string. */
  280.  
  281. void    ccatpadnum(char *cptr, char padChr, short minApnd, short maxApnd, long v, short base)
  282. {
  283.     ccpypadnum(cptr + clen(cptr), padChr, minApnd, maxApnd, v, base);
  284. }
  285.  
  286. void    ccatnum(char *cptr, long v, short base)
  287. {
  288.     ccpynum(cptr + clen(cptr), v, base);
  289. }
  290.  
  291.  
  292.  
  293. /*****************************************************************************/
  294.  
  295.  
  296.  
  297. void    ccpychr(char *cptr, char c, short count)
  298. {
  299.     for (;count--; ++cptr) *cptr = c;
  300.     *cptr = 0;
  301. }
  302.  
  303.  
  304.  
  305. /*****************************************************************************/
  306.  
  307.  
  308.  
  309. void    ccpypaddec(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  310. {
  311.     ccpypadnum(cptr, padChr, minApnd, maxApnd, v, -10);
  312. }
  313.  
  314. void    ccpydec(char *cptr, long v)
  315. {
  316.     ccpynum(cptr, v, -10);
  317. }
  318.  
  319.  
  320.  
  321. /*****************************************************************************/
  322.  
  323.  
  324.  
  325. void    ccpypadhex(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  326. {
  327.     cptr[0] = 0;
  328.     ccatpadhex(cptr, padChr, minApnd, maxApnd, v);
  329. }
  330.  
  331. void    ccpyhex(char *cptr, long v)
  332. {
  333.     cptr[0] = 0;
  334.     ccathex(cptr, v);
  335. }
  336.  
  337.  
  338.  
  339. /*****************************************************************************/
  340.  
  341.  
  342.  
  343. void    ccpypadnum(char *cptr, char padChr, short minApnd, short maxApnd, long v, short base)
  344. {
  345.     pcpypadnum((StringPtr)cptr, padChr, minApnd, maxApnd, v, base);
  346.     p2c((StringPtr)cptr);
  347. }
  348.  
  349. void    ccpynum(char *cptr, long v, short base)
  350. {
  351.     pcpynum((StringPtr)cptr, v, base);
  352.     p2c((StringPtr)cptr);
  353. }
  354.  
  355.  
  356.  
  357. /*****************************************************************************/
  358. /*****************************************************************************/
  359. /*****************************************************************************/
  360.  
  361.  
  362.  
  363. long    c2dec(char *cptr, short *charsUsed)
  364. {
  365.     return(c2num(cptr, 10, charsUsed));
  366. }
  367.  
  368.  
  369.  
  370. /*****************************************************************************/
  371.  
  372.  
  373.  
  374. long    c2hex(char *cptr, short *charsUsed)
  375. {
  376.     return(c2num(cptr, 16, charsUsed));
  377. }
  378.  
  379.  
  380.  
  381. /*****************************************************************************/
  382.  
  383.  
  384.  
  385. long    c2num(char *cptr, short base, short *charsUsed)
  386. {
  387.     Boolean    firstDigit;
  388.     short    i, sgn;
  389.     short    c;
  390.     long    val;
  391.  
  392.     sgn = 1;
  393.     for (firstDigit = false, val = 0, i = 0;;) {
  394.         c = cptr[i++];
  395.         if (base == 256) {
  396.             if (!c) break;
  397.             if (c == '\'') {
  398.                 ++i;
  399.                 break;
  400.             }
  401.             val *= base;
  402.             val += c;
  403.             continue;
  404.         }
  405.         if (c == '-') {
  406.             if (firstDigit) break;
  407.             if (sgn == -1)  break;
  408.             sgn = -1;
  409.             continue;
  410.         }
  411.         if (c == '$') {
  412.             if (firstDigit) break;
  413.             base = 16;
  414.             continue;
  415.         }
  416.         if (gHandleChars) {
  417.             if (c == '\'') {
  418.                 if (firstDigit) break;
  419.                 base = 256;
  420.                 continue;
  421.             }
  422.         }
  423.         if (base == 10) {
  424.             if (c < '0') break;
  425.             if (c > '9') break;
  426.         }
  427.         if ((!firstDigit) && (c == ' ')) continue;
  428.         c -= '0';
  429.         if (base == 16) {
  430.             if (c > 16) c -= 7;        /* Make 'A' a 10, etc. */
  431.             if (c > 32) c -= 32;    /* Make lower-case upper-case. */
  432.         }
  433.         if (c < 0) break;
  434.         if (c >= base) break;
  435.         val *= base;
  436.         val += (c * sgn);
  437.         firstDigit = true;
  438.     }
  439.  
  440.     if (charsUsed) *charsUsed = --i;
  441.  
  442.     gBase = base;
  443.     return(val);
  444. }
  445.  
  446.  
  447.  
  448. /*****************************************************************************/
  449.  
  450.  
  451.  
  452. short    GetLastBase(Boolean handleChars)
  453. {
  454.     gHandleChars = handleChars;
  455.     return(gBase);
  456. }
  457.  
  458.  
  459.  
  460. /*****************************************************************************/
  461. /*****************************************************************************/
  462. /*****************************************************************************/
  463.  
  464.  
  465.  
  466. /* Catenate a single character multiple times onto the designated string. */
  467.  
  468. void    pcatchr(StringPtr pptr, char c, short count)
  469. {
  470.     while (count--) pptr[++(pptr[0])] = c;
  471. }
  472.  
  473.  
  474.  
  475. /*****************************************************************************/
  476.  
  477.  
  478.  
  479. void    pcatpaddec(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  480. {
  481.     pcatpadnum(pptr, padChr, minApnd, maxApnd, v, -10);
  482. }
  483.  
  484. void    pcatdec(StringPtr pptr, long v)
  485. {
  486.     pcatnum(pptr, v, -10);
  487. }
  488.  
  489.  
  490.  
  491. /*****************************************************************************/
  492.  
  493.  
  494.  
  495. void    pcatpadhex(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  496. {
  497.     char    str[33];
  498.  
  499.     ccpypadhex(str, padChr, minApnd, maxApnd, v);
  500.     c2p(str);
  501.     pcat(pptr, (StringPtr)str);
  502. }
  503.  
  504. void    pcathex(StringPtr pptr, long v)
  505. {
  506.     pcatpadhex(pptr, 0, 0, 8, v);
  507. }
  508.  
  509.  
  510.  
  511. /*****************************************************************************/
  512.  
  513.  
  514.  
  515. long    pcatnum(StringPtr pptr, long v, short base)
  516. {
  517.     unsigned long    j, vv;
  518.  
  519.     vv = v;
  520.     if (base < 0) {
  521.         base = -base;
  522.         if (v < 0) {
  523.             pptr[++*pptr] = '-';
  524.             vv = -vv;
  525.         }
  526.     }
  527.     j = 0;
  528.     if (vv >= base)
  529.         j = pcatnum(pptr, vv / base, base);
  530.  
  531.     pptr[++*pptr] = "0123456789ABCDEF"[vv - j];
  532.     return(base * vv);
  533. }
  534.  
  535. void    pcatpadnum(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v, short base)
  536. {
  537.     Str32    str;
  538.  
  539.     pcpynum(str, v, base);        /* Generate minimum-digit hex value. */
  540.  
  541.     if (str[0] > maxApnd) str[0] = maxApnd;
  542.  
  543.     if (str[0] < minApnd)
  544.         if (padChr)
  545.             pcatchr(pptr, padChr, (minApnd - str[0]));
  546.                 /* if we have a pad character, and if necessary, pad the string. */
  547.  
  548.     pcat(pptr, str);            /* Add the hex digits to the string. */
  549. }
  550.  
  551.  
  552.  
  553. /*****************************************************************************/
  554.  
  555.  
  556.  
  557. void    pcpychr(StringPtr pptr, char c, short count)
  558. {
  559.     pptr[0] = 0;
  560.     pcatchr(pptr, c, count);
  561. }
  562.  
  563.  
  564.  
  565. /*****************************************************************************/
  566.  
  567.  
  568.  
  569. void    pcpypaddec(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  570. {
  571.     *pptr = 0;
  572.     pcatpaddec(pptr, padChr, minApnd, maxApnd, v);
  573. }
  574.  
  575. void    pcpydec(StringPtr pptr, long v)
  576. {
  577.     *pptr = 0;
  578.     pcatdec(pptr, v);
  579. }
  580.  
  581.  
  582.  
  583. /*****************************************************************************/
  584.  
  585.  
  586.  
  587. void    pcpypadnum(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v, short base)
  588. {
  589.     *pptr = 0;
  590.     pcatpadnum(pptr, padChr, minApnd, maxApnd, v, base);
  591. }
  592.  
  593. void    pcpynum(StringPtr pptr, long v, short base)
  594. {
  595.     *pptr = 0;
  596.     pcatnum(pptr, v, base);
  597. }
  598.  
  599.  
  600.  
  601. /*****************************************************************************/
  602.  
  603.  
  604.  
  605. void    pcpypadhex(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  606. {
  607.     *pptr = 0;
  608.     pcatpadhex(pptr, padChr, minApnd, maxApnd, v);
  609. }
  610.  
  611. void    pcpyhex(StringPtr pptr, long v)
  612. {
  613.     pcpypadhex(pptr, 0, 0, 8, v);
  614. }
  615.  
  616.  
  617.  
  618. /*****************************************************************************/
  619.  
  620.  
  621.  
  622. long    p2dec(StringPtr pptr, short *charsUsed)
  623. {
  624.     return(p2num(pptr, 10, charsUsed));
  625. }
  626.  
  627.  
  628.  
  629. /*****************************************************************************/
  630.  
  631.  
  632.  
  633. long    p2hex(StringPtr pptr, short *charsUsed)
  634. {
  635.     return(p2num(pptr, 16, charsUsed));
  636. }
  637.  
  638.  
  639.  
  640. /*****************************************************************************/
  641.  
  642.  
  643.  
  644. long    p2num(StringPtr pptr, short base, short *charsUsed)
  645. {
  646.     long    val;
  647.  
  648.     p2c(pptr);
  649.     val = c2num((char *)pptr, base, charsUsed);
  650.     c2p((char *)pptr);
  651.     return(val);
  652. }
  653.  
  654.  
  655.  
  656. /*****************************************************************************/
  657. /*****************************************************************************/
  658. /*****************************************************************************/
  659.  
  660.  
  661.  
  662. short    GetHexByte(char *cptr)
  663. {
  664.     short    val, i, chr;
  665.  
  666.     for (val = 0, i = 0; i < 2; ++i) {
  667.         chr = cptr[i];
  668.         if (chr == '=') return(cptr[++i]);
  669.         if (chr == '≈') {
  670.             chr = cptr[++i];
  671.             if ((chr >= 'a') && (chr <= 'z')) chr -= 32;
  672.             return(chr);
  673.         }
  674.         if (chr > 'F')
  675.             chr -= 0x20;
  676.         if (chr > '9')
  677.             chr -= ('A' - '9' - 1);
  678.         val = (val << 4) + chr - '0';
  679.     }
  680.     return(val);
  681. }
  682.  
  683.  
  684.  
  685. /*****************************************************************************/
  686.  
  687.  
  688.  
  689. Boolean    EqualHandle(void *h1, void *h2)
  690. {
  691.     long    s1, s2;
  692.     Ptr        p1, p2;
  693.  
  694.     if ((h1) && (!h2)) return(false);
  695.     if ((h2) && (!h1)) return(false);
  696.     if ((s1 = GetHandleSize(h1)) != (s2 = GetHandleSize(h2))) return(false);
  697.  
  698.     p1 = *(Handle)h1;
  699.     p2 = *(Handle)h2;
  700.     for (s1 = 0; s1 < s2; ++s1)
  701.         if (p1[s1] != p2[s1]) return(false);
  702.         
  703.     return(true);
  704. }
  705.  
  706.  
  707.  
  708. /*****************************************************************************/
  709.  
  710.  
  711.  
  712. Boolean    EqualData(void *v1, void *v2, long size)
  713. {
  714.     Ptr        p1, p2;
  715.     long    ii;
  716.  
  717.     if ((v1) && (!v2)) return(false);
  718.     if ((v2) && (!v1)) return(false);
  719.  
  720.     p1 = (Ptr)v1;
  721.     p2 = (Ptr)v2;
  722.     for (ii = 0; ii < size; ++ii)
  723.         if (p1[ii] != p2[ii]) return(false);
  724.         
  725.     return(true);
  726. }
  727.  
  728.  
  729.  
  730. /*****************************************************************************/
  731.  
  732.  
  733.  
  734. void    SetMem(void *vptr, unsigned char c, unsigned long len)
  735. {
  736.     Ptr    ptr;
  737.  
  738.     ptr = (Ptr)vptr;
  739.     while (len--) *ptr++ = c;
  740. }
  741.  
  742.  
  743.  
  744. /*****************************************************************************/
  745.  
  746.  
  747.  
  748. OSErr    HInsert(Handle hh, long offset, void *dataptr, long delta);
  749. OSErr    HInsert(Handle hh, long offset, void *dataptr, long delta)
  750. {
  751.     long    dataSize;
  752.     char    *cptr;
  753.     OSErr    err;
  754.  
  755.     dataSize = GetHandleSize(hh);
  756.  
  757.     if (!(delta & 0x80000000L)) {
  758.         SetHandleSize(hh, dataSize + delta);
  759.         err = MemError();
  760.         if (err) return(err);
  761.     }
  762.     else {
  763.         offset -= delta;
  764.             /* We are removing what we are pointing/offset at, so the block that is to be moved is
  765.             ** after the data being removed at the offset.  The size of the data being removed is
  766.             ** i-delta, so therefore subtract this negative number from offset to skip past data. */
  767.     }
  768.  
  769.     cptr = (*(char **)hh) + offset;
  770.     BlockMove(cptr, cptr + delta, dataSize - offset);
  771.  
  772.     if (delta & 0x80000000L) {
  773.         SetHandleSize(hh, dataSize + delta);
  774.             /* Delta is negative -- we are deleting data.  dataptr is unused. */
  775.     }
  776.     else {
  777.         cptr = (*(char **)hh) + offset;
  778.         BlockMove(dataptr, cptr, delta);
  779.             /* Delta is positive -- we are adding data pointed at by dataptr. */
  780.     }
  781.  
  782.     return(noErr);
  783. }
  784.  
  785.  
  786.  
  787.